<?php

namespace App\Service\Kms\Task\Common;

use App\Models\Kms\Task\DailyTaskLogsModel;
use App\Models\Kms\Task\TaskModel;
use App\Models\Kms\Task\TaskNodesModel;
use App\Models\Kms\Task\TaskTemplateModel;
use App\Models\Kms\Task\TaskTemplateNodesModel;
use App\Models\Kms\Task\TaskTemplateNodesProcessorModel;
use Exception;
use Illuminate\Support\Collection;

abstract class BaseTask
{
    private function __construct() { }

    /**
     * @param int $templateType
     * @return ChatDailyTask|KmsDailyTask|void
     */
    public static function getTaskInstance(int $templateType)
    {
        switch ($templateType){
            case TaskTemplateModel::TEMPLATE_TYPE_0:
                return new KmsDailyTask();
            case TaskTemplateModel::TEMPLATE_TYPE_1:
                return new ChatDailyTask();
        }
    }

    /**
     * 获取任务节点信息
     *
     * @return array
     */
    abstract function getTaskNode(): array;

    /**
     * 节点完成事件处理
     *
     * @param TaskModel $taskModel
     * @return mixed
     */
    abstract function handleTaskNodeFinishEvent(TaskModel $taskModel);

    /**
     * 任务创建事件处理
     *
     * @param DailyTaskLogsModel $dailyTaskLogsModel
     * @param Collection $userCollection
     * @return void
     * @throws Exception
     */
    public function handleTaskCreateEvent(DailyTaskLogsModel $dailyTaskLogsModel, Collection $userCollection)
    {
        //todo 任务模板添加
        $taskTemplateModel = TaskTemplateModel::generateTemplate(
            $dailyTaskLogsModel->createdByUid,
            $dailyTaskLogsModel->templateType,
            TaskTemplateModel::SOURCE_SYSTEM
        );

        $approveUserIds = jsonToArr($dailyTaskLogsModel->approveUserIds, []);
        $step           = 0;

        // todo 任务模板节点添加
        collect($this->getTaskNode())->map(function ($taskNode, $businessType) use (
            $taskTemplateModel,
            $dailyTaskLogsModel,
            $approveUserIds,
            &$step,
            $userCollection
        ) {
            if ($businessType == TaskTemplateNodesModel::BUSINESS_TYPE_APPROVE) {
                $approveType = TaskTemplateNodesModel::APPROVAL_TYPE_PRE_NODE;
                $preStep     = $step;
            } else {
                $approveType = TaskTemplateNodesModel::APPROVAL_TYPE_DEFAULT;
                $preStep     = $step + 1;
            }

            $taskTemplateNodesModel = TaskTemplateNodesModel::query()->create([
                "templateId"               => $taskTemplateModel->id,
                "step"                     => $step + 1,
                "preStep"                  => $preStep,
                "businessType"             => $businessType,
                "businessTypeText"         => TaskTemplateNodesModel::BUSINESS_TYPE_TEXT[$businessType] ?? "",
                "businessStatusEnum"       => collect($taskNode["businessStatusEnum"])
                    ->map(function ($text, $val) {
                        return [
                            "status"       => $val,
                            "text"         => $text,
                            "originalText" => TaskNodesModel::BUSINESS_STATUS_TEXT[$val] ?? ""
                        ];
                    })->values()->toJson(JSON_UNESCAPED_UNICODE),
                "rejectBusinessStatusEnum" => collect($taskNode["rejectBusinessStatusEnum"])
                    ->map(function ($text, $val) {
                        return [
                            "status" => $val,
                            "text"   => $text
                        ];
                    })->values()->toJson(JSON_UNESCAPED_UNICODE),
                "approveType"              => $approveType,
                "createdAt"                => time(),
                "createdByUid"             => $dailyTaskLogsModel->createdByUid
            ]);

            switch ($businessType) {
                case TaskTemplateNodesModel::BUSINESS_TYPE_GENERATE:
                    $handlerUserId = $dailyTaskLogsModel->createdByUid;
                    break;
                case TaskTemplateNodesModel::BUSINESS_TYPE_SUBMIT:
                    $handlerUserId = $dailyTaskLogsModel->handlerUserId;
                    break;
                case TaskTemplateNodesModel::BUSINESS_TYPE_APPROVE:
                    $handlerUserId = $approveUserIds;
                    break;
                default:
                    $handlerUserId = 0;
                    break;
            }

            if (is_array($handlerUserId)) {
                collect($handlerUserId)->each(function ($handlerUserId) use (
                    $taskTemplateNodesModel,
                    $dailyTaskLogsModel,
                    $userCollection
                ) {
                    TaskTemplateNodesProcessorModel::query()->create([
                        "nodeId"          => $taskTemplateNodesModel->id,
                        "handlerUserType" => TaskTemplateNodesProcessorModel::HANDLER_USER_TYPE_0,
                        "handlerUserId"   => $handlerUserId,
                        "handlerUsername" => $this->getUsername($handlerUserId, $userCollection),
                        "createdAt"       => time(),
                        "createdByUid"    => $dailyTaskLogsModel->createdByUid
                    ]);
                });
            } else {
                TaskTemplateNodesProcessorModel::query()->create([
                    "nodeId"          => $taskTemplateNodesModel->id,
                    "handlerUserType" => TaskTemplateNodesProcessorModel::HANDLER_USER_TYPE_0,
                    "handlerUserId"   => $handlerUserId,
                    "handlerUsername" => $this->getUsername($handlerUserId, $userCollection),
                    "createdAt"       => time(),
                    "createdByUid"    => $dailyTaskLogsModel->createdByUid
                ]);
            }

            $step++;
        })->values()->toArray();

        // todo 生成任务
        $taskModel = (new TaskService())->generateTask(
            $taskTemplateModel,
            $dailyTaskLogsModel->id,
            $dailyTaskLogsModel->createdByUid
        );

        // todo 任务跳转到下一节点
        (new TaskService())->nextNode($taskModel, $dailyTaskLogsModel->createdByUid);
    }

    /**
     * 获取用户名称
     *
     * @param int $uid
     * @param Collection $userGroup
     * @return string
     */
    public function getUsername(int $uid, Collection $userGroup): string
    {
        if (empty($uid)) {
            return "系统";
        }

        $handlerUser = $userGroup->where("rmsUserId", $uid)->first();
        if (empty($handlerUser)) {
            return "-";
        }
        return vsprintf(
            "%s(%s)",
            [
                attributeGet($handlerUser, "name", ""),
                attributeGet($handlerUser, "nickname", "")
            ]
        );
    }
}
